#include "StdAfx.hpp"

#include "X.hpp"

#include <cstdio>
#include <iostream>

X::X() : m_double(0) {
    printf("X::X(): no args\n");
}

X::X(int i) : m_double(i) {
    printf("X::X(int i): i = %d\n", i);
}

X::X(double d) : m_double(d) {
    printf("X::X(double d): d = %g\n", d);
}

X::X(const wchar_t *s) : X(999) {
    wprintf(L"X::X(const wchar_t *s): s = %s\n", s);
}

long X::DoFunc1() {
    return Func1();
}

long X::Func1() {
    printf("long X::Func1(): no args\n");
    return 100;
}

long X::Func1() const {
    printf("long X::Func1() const: no args\n");
    return 100100;
}

void X::Func2(long y) {
    printf("void X::Func2(long): y = %d\n", y);
}

int X::Func2(double d) {
    printf("int X::Func2(double): d = %g\n", d);
    return -1000;
}

float X::Func2(double d) const {
    printf("int X::Func2(double) const: d = %g\n", d);
    return -1001;
}

void X::Static(unsigned u) {
    printf("void X::Static(unsigned): u = %d\n", u);
}

short X::Func3(unsigned short s) {
    printf("short X::Func3(unsigned short): s = %d\n", s);
    return 127;
}

char X::Func4(unsigned char ch) {
    printf("char X::Func4(unsigned char): ch = %d\n", ch);
    return 'a';
}

void XBase::Func1(const char *s) {
    printf("void XBase::Func1(const char *s) -- %s\n", s);
}

void XBase::ProtectedVirtual() {
    printf("void XBase::ProtectedVirtual()\n");
}

ZBase::ZBase() : z0(1234) {}

Z::Z(int z) : z(z), px(NULL) {}

void Z::ZZ() {
    printf("void Z::ZZ() -- z: %d\n", z);
}

X Z::GetXInstance() const {
    return X();
}

void Z::SetXInstance(X x) const {
    printf("void Z::SetXInstance(X x) const -- x.m_double = %g\n", x.GetDouble());
}

void Z::PrintZ() const {
    printf("void Z::PrintZ() const -- z: %d\n", z);
}

void PrivateDestructor::PrintM() const {
    printf("PrivateDestructor::PrintM() const -- m: %d\n", m);
}

void PrivateDestructor::V() {
    printf("void PrivateDestructor::V()\n");
}

void PrivatePureVirtual::DoPV() {
    printf("void Y::DoPV(): no args\n");
    PV();
}

ProtectedMembers::ProtectedMembers() {}

void ProtectedMembers::InvokeProtected() {
    printf("ProtectedMembers::InvokeProtected()\n");
}

void X::Inner::Print() {
    printf("X::Inner::Print() == %d\n", IN_FLAG);
}

void X::Inner::MostInner::Print() {
    printf("X::Inner::MostInner::Print() == %d\n", MIN_FLAG);
}

FP SetFP(FP fp) {
    printf("FP SetFP(FP fp)\n");
    return fp;
}

FP SetFP(MyColor::Channel(MyColor::*FPM)() const) {
    printf("FP SetFP(MyColor::Channel(MyColor::*FPM)() const)\n");
    return NULL;
}

unsigned char Drawable::MSW::Color::Red() const {
    printf("unsigned char Drawable::Color::Red()\n");
    return 127;
}

bool Drawable::MSW::Create(Type tp, bool in_memory) {
    printf("bool Drawable::MSW::Create(Type tp, bool in_memory)\n");
    printf("==>  tp: %d, in_memory: %d\n", tp, in_memory);

    return true;
}

Drawable::Type Drawable::MSW::GetType() {
    printf("Drawable::Type Drawable::MSW::GetType()\n");
    return Drawable::BITMAP;
}

MyColor::Channel MyColor::Green() const {
    printf("MyColor::Channel MyColor::Green() const\n");
    return 255;
}

namespace {
    struct MyStruct    {
        int u, v, w;
    };
}

namespace Drawable {
    namespace MSW {
        Color WHITE;
    }
}

//////////////////////////////////////////////////////////////////////////

Z _z(1401214306);
Z *_pz = &_z;
const double PI = 3.141592657;
const wchar_t *EmptyString = L"";
const char wxToolBarNameStr[] = "DefToolBar";
char * const ConstPtr = nullptr;
const char *p = wxToolBarNameStr;
int MyVar = 20141001;
Var<int> MyVarInt = { 20141012 };

void Test101() {
    MyStruct ms;
    ms.u = 123;
}

int F1(int x, int y, double z) {
    printf("F1(%d, %d, %g)\n", x, y, z);
    return 20140929;
}

void F2(int *i, unsigned short *s, Z *p, const Z &z) {
    printf("F2(0x%p, 0x%p, 0x%p, %d)\n", i, s, p, z.GetValue());

    if (i) {
        printf("*i = %d\n", *i);
    }

    if (s) {
        printf("*s = %d\n", *s);
    }

    if (p) {
        printf("p->z = %d\n", p->GetValue());
    }
}

void F3(bool b, Z &z) {
    printf("F3(%d, %d)\n", b, z.GetValue());
}

void F4(const wchar_t *msg) {
    wprintf(L"F4(%s)\n", msg ? msg : L"<NULL>");
}

void F5(const char * msg) {
    printf("F5(%s)\n", msg ? msg : "<NULL>");
}

void X_Injected(X *x) {
    printf("void X_Injected() -- %g\n", x->GetDouble());
}

//////////////////////////////////////////////////////////////////////////

std::vector<int> _vi = { 100, 101, 102 };

template <typename T>
void PrintVector(const std::vector<T> &v) {
    for (auto &item : v) {
        std::cout << item << ' ';
    }

    printf("\n");
}

void TestVector(const std::vector<int> &vi) {
    PrintVector(vi);
}

void TestVector2(std::vector<int> &vi) {
    PrintVector(vi);

    vi.push_back(999);
    vi.push_back(1999);
}

void TestVector3(std::vector<double> &vd) {
    PrintVector(vd);

    vd.clear();
}

void TestVector4(std::vector<double> *vd) {
    if (vd) {
        TestVector3(*vd);
    }
    else {
        std::cout << "void TestVector4(<** NULL **>)" << std::endl;
    }
}

//////////////////////////////////////////////////////////////////////////

const MyDict &GetDict() {
    static MyDict d;

    if (d.empty()) {
        d[L"age"] = 24;
        d[L"height"] = 165;
    }

    return d;
}

MyDict _d(GetDict());

template <typename K, typename V>
void PrintDict(const std::map<K, V> &d) {
    for (auto &kv : d) {
        std::wcout << kv.first << L" -> " << kv.second << std::endl;
    }

    printf("\n");
}

void TestDict(MyDict &d) {
    PrintDict(d);
    d[L"Z"] = 90;
}

#include "Gen/_Common.hxx"

int TestPyObject(PyObject *obj) {
    PBPP_NEW_THREAD_BLOCKER
    int ret = PyInt_AsSsize_t(obj) + 100;
    return ret;
}

PyObject * X_Injected2(X *xx) {
    printf("PyObject * X_Injected2(X *xx) -- ");

    int x = 100, y = 101;
    return pbpp::PackAsTuple({ x, y });
}
